package helper

import (
	"bufio"
	"context"
	"strings"
	"time"

	"server/config"
	"server/core"

	"github.com/gookit/color"
)

func stringToLines(s string) (lines []string, err error) {
	scanner := bufio.NewScanner(strings.NewReader(s))
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	err = scanner.Err()
	return
}

func stringToKV(s string) (string, string) {
	ss := strings.Split(s, ":")
	if len(ss) < 2 {
		return s, ""
	}
	return ss[0], ss[1]
}

func Info(sections ...string) (res map[string]string) {
	infoStr, err := core.RDB.Info(context.Background(), sections...).Result()
	res = map[string]string{}
	if err != nil {
		color.Red.Println("redis.Info err: ", err)
		return res
	}
	lines, err := stringToLines(infoStr)
	if err != nil {
		color.Red.Println("stringToLines err: ", err)
		return res
	}
	for i := 0; i < len(lines); i++ {
		if lines[i] == "" || strings.HasPrefix(lines[i], "# ") {
			continue
		}
		k, v := stringToKV(lines[i])
		res[k] = v
	}
	return res
}

func DBSize() int64 {
	size, err := core.RDB.DBSize(context.Background()).Result()
	if err != nil {
		color.Red.Println("redis.DBSize err: ", err)
		return 0
	}
	return size
}

func Set(key string, value any, timeSec int) bool {
	err := core.RDB.Set(context.Background(),
		config.Config.Redis.Prefix+key, value, time.Duration(timeSec)*time.Second).Err()
	if err != nil {
		color.Red.Println("redis.Set err: ", err)
		return false
	}
	return true
}

// Get 获取key的值
func Get(key string) string {
	res, err := core.RDB.Get(context.Background(), config.Config.Redis.Prefix+key).Result()
	if err != nil {
		color.Red.Println("redis.Get err: ", err)
		return ""
	}
	return res
}

// SSet 将数据放入set缓存
func SSet(key string, values ...any) bool {
	err := core.RDB.SAdd(context.Background(), config.Config.Redis.Prefix+key, values...).Err()
	if err != nil {
		color.Red.Println("redis.SSet err: ", err)
		return false
	}
	return true
}

// SGet 根据key获取Set中的所有值
func SGet(key string) []string {
	res, err := core.RDB.SMembers(context.Background(), config.Config.Redis.Prefix+key).Result()
	if err != nil {
		color.Red.Println("redis.SGet err: ", err)
		return []string{}
	}
	return res
}

// HMSet 设置key, 通过字典的方式设置多个field, value对
func HMSet(key string, mapping map[string]string, timeSec int) bool {
	err := core.RDB.HSet(context.Background(), config.Config.Redis.Prefix+key, mapping).Err()
	if err != nil {
		color.Red.Println("redis.HMSet err: ", err)
		return false
	}
	if timeSec > 0 {
		if !Expire(key, timeSec) {
			return false
		}
	}
	return true
}

// HSet 向hash表中放入数据,如果不存在将创建
func HSet(key string, field string, value string, timeSec int) bool {
	return HMSet(key, map[string]string{field: value}, timeSec)
}

// HGet 获取key中field域的值
func HGet(key string, field string) string {
	res, err := core.RDB.HGet(context.Background(), config.Config.Redis.Prefix+key, field).Result()
	if err != nil {
		color.Red.Println("redis.HGet err: ", err)
		return ""
	}
	return res
}

// HExists 判断key中有没有field域名
func HExists(key string, field string) bool {
	res, err := core.RDB.HExists(context.Background(), config.Config.Redis.Prefix+key, field).Result()
	if err != nil {
		color.Red.Println("redis.HExists err: ", err)
		return false
	}
	return res
}

// HDel 删除hash表中的值
func HDel(key string, fields ...string) bool {
	err := core.RDB.HDel(context.Background(), config.Config.Redis.Prefix+key, fields...).Err()
	if err != nil {
		color.Red.Println("redis.HDel err: ", err)
		return false
	}
	return true
}

// Exists 判断多项key是否存在
func Exists(keys ...string) int64 {
	fullKeys := toFullKeys(keys)
	cnt, err := core.RDB.Exists(context.Background(), fullKeys...).Result()
	if err != nil {
		color.Red.Println("redis.Exists err: ", err)
		return -1
	}
	return cnt
}

// Expire 指定缓存失效时间
func Expire(key string, timeSec int) bool {
	err := core.RDB.Expire(context.Background(), config.Config.Redis.Prefix+key, time.Duration(timeSec)*time.Second).Err()
	if err != nil {
		color.Red.Println("redis.Expire err: ", err)
		return false
	}
	return true
}

// TTL 根据key获取过期时间
func TTL(key string) int {
	td, err := core.RDB.TTL(context.Background(), config.Config.Redis.Prefix+key).Result()
	if err != nil {
		color.Red.Println("redis.TTL err: ", err)
		return 0
	}
	return int(td / time.Second)
}

// Del 删除一个或多个键
func Del(keys ...string) bool {
	fullKeys := toFullKeys(keys)
	err := core.RDB.Del(context.Background(), fullKeys...).Err()
	if err != nil {
		color.Red.Println("redis.Del err: ", err)
		return false
	}
	return true
}

// toFullKeys 为keys批量增加前缀
func toFullKeys(keys []string) (fullKeys []string) {
	for _, k := range keys {
		fullKeys = append(fullKeys, config.Config.Redis.Prefix+k)
	}
	return
}
